﻿namespace MicroCloud
{
    #region "组织机构扩展方法"
    /// <summary>
    /// 组织机构扩展方法
    /// </summary>
    public static class OrganizationExtensions
    {
        #region "扩展方法"
        #region "将简单组织机构DTO转换为节点对象"
        /// <summary>
        /// 将简单组织机构DTO转换为节点对象
        /// </summary>
        /// <param name="dto">简单组织机构DTO</param>
        /// <returns></returns>
        public static OrganizationNode ToNode(this OrganizationDtoSimple dto)
        {
            if (dto == null)
            {
                return null;
            }
            var node = dto.MapTo<OrganizationDtoSimple, OrganizationNode>();
            return node;
        }
        #endregion
        #region "将简单组织机构DTO转换为身份对象"
        /// <summary>
        /// 将简单组织机构DTO转换为身份对象
        /// </summary>
        /// <param name="dto">简单组织机构DTO</param>
        /// <returns></returns>
        public static OrganizationIdentity ToIdentity(this OrganizationDtoSimple dto)
        {
            var node = dto.ToNode();
            if (node == null)
            {
                return null;
            }
            var identity = node.MapTo<OrganizationNode, OrganizationIdentity>();
            return identity;
        }
        #endregion

        #region "将简单组织机构DTO集合转换为节点对象集合"
        /// <summary>
        /// 将简单组织机构DTO集合转换为节点对象集合
        /// </summary>
        /// <param name="dtos">简单组织机构DTO集合</param>
        /// <param name="excludeNull">排除Null值对象</param>
        /// <param name="removeDuplicate">去除重复对象</param>
        /// <returns></returns>
        public static ICollection<OrganizationNode> ToNodes(this ICollection<OrganizationDtoSimple> dtos, bool excludeNull = true, bool removeDuplicate = true)
        {
            List<OrganizationNode> nodes = new();
            if (dtos == null)
            {
                return nodes;
            }
            foreach (var dto in dtos)
            {
                if (dto == null && excludeNull)
                {
                    continue;
                }
                if (removeDuplicate)
                {
                    nodes.AddIfNotExist(dto.ToNode());
                }
                else
                {
                    nodes.Add(dto.ToNode());
                }
            }
            return nodes;
        }
        #endregion
        #region "将简单组织机构DTO集合转换为身份对象集合"
        /// <summary>
        /// 将简单组织机构DTO集合转换为身份对象集合
        /// </summary>
        /// <param name="dtos">简单组织机构DTO集合</param>
        /// <param name="excludeNull">排除Null值对象</param>
        /// <param name="removeDuplicate">去除重复对象</param>
        /// <returns></returns>
        public static ICollection<OrganizationIdentity> ToIdentities(this ICollection<OrganizationDtoSimple> dtos, bool excludeNull = true, bool removeDuplicate = true)
        {
            List<OrganizationIdentity> identities = new();
            if (dtos == null)
            {
                return identities;
            }
            foreach (var dto in dtos)
            {
                if (dto == null && excludeNull)
                {
                    continue;
                }
                if (removeDuplicate)
                {
                    identities.AddIfNotExist(dto.ToIdentity());
                }
                else
                {
                    identities.Add(dto.ToIdentity());
                }
            }
            return identities;
        }
        #endregion

        #region "将节点对象转换为简单组织机构DTO"
        /// <summary>
        /// 将节点对象转换为简单组织机构DTO
        /// </summary>
        /// <param name="node">节点对象</param>
        /// <returns></returns>
        public static OrganizationDtoSimple ToDtoSimple(this OrganizationNode node)
        {
            if (node == null)
            {
                return null;
            }
            var dto = node.MapTo<OrganizationNode, OrganizationDtoSimple>();
            return dto;
        }
        #endregion
        #region "将节点对象集合转换为简单组织机构DTO集合"
        /// <summary>
        /// 将节点对象集合转换为简单组织机构DTO集合
        /// </summary>
        /// <param name="nodes">节点对象集合</param>
        /// <param name="excludeNull">排除Null值对象</param>
        /// <param name="removeDuplicate">去除重复对象</param>
        /// <returns></returns>
        public static ICollection<OrganizationDtoSimple> ToDtoSimples(this ICollection<OrganizationNode> nodes, bool excludeNull = true, bool removeDuplicate = true)
        {
            List<OrganizationDtoSimple> dtos = new();
            if (nodes == null)
            {
                return dtos;
            }
            foreach (var node in nodes)
            {
                if (node == null && excludeNull)
                {
                    continue;
                }
                if (removeDuplicate)
                {
                    dtos.AddIfNotExist(node.ToDtoSimple());
                }
                else
                {
                    dtos.Add(node.ToDtoSimple());
                }
            }
            return dtos;
        }
        #endregion

        #region "将简单组织机构DTO集合转换为树形节点对象集合"
        /// <summary>
        /// 将简单组织机构DTO集合转换为树形节点对象集合
        /// </summary>
        /// <param name="dtos">简单组织机构DTO集合</param>
        /// <param name="excludeNull">排除Null值对象</param>
        /// <param name="removeDuplicate">去除重复对象</param>
        /// <returns></returns>
        public static ICollection<OrganizationTreeNode> ToTreeNodes(this ICollection<OrganizationDtoSimple> dtos, bool excludeNull = true, bool removeDuplicate = true)
        {
            var treeNodes = dtos.ToNodes(excludeNull, removeDuplicate).ToTreeNodes(excludeNull, removeDuplicate);
            return treeNodes;
        }
        #endregion
        #region "将节点对象集合转换为树形节点对象集合"
        /// <summary>
        /// 将节点对象集合转换为树形节点对象集合
        /// </summary>
        /// <param name="nodes">节点对象集合</param>
        /// <param name="excludeNull">排除Null值对象</param>
        /// <param name="removeDuplicate">去除重复对象</param>
        /// <returns></returns>
        public static ICollection<OrganizationTreeNode> ToTreeNodes(this ICollection<OrganizationNode> nodes, bool excludeNull = true, bool removeDuplicate = true)
        {
            List<OrganizationTreeNode> treeNodes = new();
            if (nodes == null)
            {
                return treeNodes;
            }
            List<OrganizationNode> nodeList = nodes.ToList();
            if (excludeNull)
            {
                nodeList = nodeList.Where(o => o != null).ToList();
            }
            if (removeDuplicate)
            {
                nodeList = nodeList.Distinct().ToList();
            }

            var parentNodeList = nodeList.Where(m => m.ParentId.IsMissing() || !nodeList.Exists(o => Equals(o.Id, m.ParentId))).ToList();
            foreach (var parentNode in parentNodeList)
            {
                var treeNode = parentNode.MapTo<OrganizationNode, OrganizationTreeNode>();
                treeNode.Items = GetTreeNodes(treeNode, nodeList);
                treeNodes.Add(treeNode);
            }
            return treeNodes;
        }
        #endregion

        #region "将树形节点对象集合转换为节点对象集合"
        /// <summary>
        /// 将树形节点对象集合转换为节点对象集合
        /// </summary>
        /// <param name="treeNodes">树形节点对象集合</param>
        /// <param name="excludeNull">排除Null值对象</param>
        /// <param name="removeDuplicate">去除重复对象</param>
        /// <returns></returns>
        public static ICollection<OrganizationNode> ToNodes(this ICollection<OrganizationTreeNode> treeNodes, bool excludeNull = true, bool removeDuplicate = true)
        {
            List<OrganizationNode> nodes = new();
            List<OrganizationTreeNode> treeNodes_tmp = new();
            if (treeNodes == null)
            {
                return nodes;
            }
            foreach (var treeNode in treeNodes)
            {
                ReverseRecursionTreeNode(treeNodes.ToList(), treeNode);
                treeNodes_tmp.Add(treeNode);
            }
            if (treeNodes_tmp == null)
            {
                foreach (var treeNode in treeNodes_tmp)
                {
                    if (treeNode == null && excludeNull)
                    {
                        continue;
                    }
                    var node = treeNode.MapTo<OrganizationTreeNode, OrganizationNode>();
                    if (removeDuplicate)
                    {
                        nodes.AddIfNotExist(node);
                    }
                    else
                    {
                        nodes.Add(node);
                    }
                }
            }
            return nodes;
        }
        #endregion

        #endregion

        #region "私有方法"
        #region "获取组织机构子树形节点"
        /// <summary>
        /// 递归树形节点对象集合，将普通List转换为树形数据结构 RecursionTreeNode
        /// </summary>
        /// <param name="treeNode">树形节点数据</param>
        /// <param name="nodes">节点对象集合</param>
        /// <returns></returns>
        private static List<OrganizationTreeNode> GetTreeNodes(OrganizationTreeNode treeNode, List<OrganizationNode> nodes)
        {
            List<OrganizationTreeNode> treeNodes = new();
            var children = nodes.Where(o => treeNode.Id == o.ParentId).OrderBy(m => m.OrderNo).ThenBy(m => m.Id).ToList();
            if (children?.Count > 0)
            {
                foreach (var child in children)
                {
                    var childTreeNode = child.MapTo<OrganizationNode, OrganizationTreeNode>();
                    if (nodes.Exists(m => Equals(m.ParentId, childTreeNode.Id)))
                    {
                        childTreeNode.Items = GetTreeNodes(childTreeNode, nodes);
                    }
                    treeNodes.Add(childTreeNode);
                }
            }
            return treeNodes;
        }
        #endregion
        #region "反向递归树形节点对象集合，将树形数据结构转换为普通List"
        /// <summary>
        /// 反向递归树形节点对象集合，将树形数据结构转换为普通List
        /// </summary>
        /// <param name="treeNodes">归树形节点对象集合</param>
        /// <param name="treeNode">归树形节点对象</param>
        private static void ReverseRecursionTreeNode(List<OrganizationTreeNode> treeNodes, OrganizationTreeNode treeNode)
        {
            if (treeNode.Items != null)
            {
                if (treeNode.Items.Count > 0)
                {
                    treeNodes.AddRange(treeNode.Items);
                    foreach (var subItem in treeNode.Items)
                    {
                        ReverseRecursionTreeNode(treeNodes, subItem);
                    }
                }
            }
        }
        #endregion

        #endregion

    }
    #endregion

}
